
#pragma once

#if defined(__GNUC__) || defined(__MINGW__) || defined(__MINGW32__)
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Weffc++"
#endif

#include "libden/meta/can_recursive_iteration.h"

#define dHEADER       \
    class Container,  \
    class ConcreteWay \


#define dSPEC    \
    Container,   \
    ConcreteWay  \

//---------------------------------------------------------------------------------------------

namespace Den{

template<dHEADER> 
    IteratorBaseWrapper<dSPEC>::IteratorBaseWrapper()
        :iterator()
        ,mContainer(nullptr)
    {}
template<dHEADER> 
    IteratorBaseWrapper<dSPEC>::IteratorBaseWrapper(cv& c, const iterator& cur )
        :iterator(cur)
        ,mContainer(&c)
    {}
template<dHEADER> 
    IteratorBaseWrapper<dSPEC>::IteratorBaseWrapper(cv& c )
        :iterator( way::Beg(c) )
        ,mContainer(&c)
    {}
template<dHEADER> 
    IteratorBaseWrapper<dSPEC>::IteratorBaseWrapper(no_cv& c, const iterator& cur )
        :iterator(cur)
        ,mContainer(&c)
    {}
template<dHEADER>
    IteratorBaseWrapper<dSPEC>::IteratorBaseWrapper(no_cv& c )
        :iterator( way::Beg(c) )
        ,mContainer(&c)
    {}
template<dHEADER> 
    IteratorBaseWrapper<dSPEC>::IteratorBaseWrapper(const IteratorBaseWrapper& rhs)
        :iterator(rhs)
        ,mContainer(rhs.mContainer)
    {}


template<dHEADER> 
    template<class U>
        IteratorBaseWrapper<dSPEC>::IteratorBaseWrapper(const IteratorBaseWrapper<U, ConcreteWay>& rhs)
            :iterator(rhs)
            ,mContainer(rhs.mContainer)
        {}

template<dHEADER> 
    IteratorBaseWrapper<dSPEC>& IteratorBaseWrapper<dSPEC>::operator=(no_cv& c)
    {
        static_cast<iterator&>(*this) = way::Beg(c);
        mContainer = &c;
        return *this;
    }

template<dHEADER> 
    IteratorBaseWrapper<dSPEC>&
        IteratorBaseWrapper<dSPEC>::operator=(cv& c)
        {
            static_cast<iterator&>(*this) = way::Beg(c);
            mContainer = &c;
            return *this;
        }

template<dHEADER> 
    template<class U>
        IteratorBaseWrapper<dSPEC>&
            IteratorBaseWrapper<dSPEC>::operator=(const IteratorBaseWrapper<U, ConcreteWay>& rhs)
            {
                static_cast<iterator&>(*this) = rhs;
                mContainer = rhs.mContainer;
                return *this;
            }

template<dHEADER> 
    IteratorBaseWrapper<dSPEC>::
        operator bool()const { return !Empty(); }

template<dHEADER> 
    bool IteratorBaseWrapper<dSPEC>::
        operator!()const { return Empty(); }

template<dHEADER> 
    bool IteratorBaseWrapper<dSPEC>::
        Beg()const   
        {
            return mContainer && 
                static_cast<const iterator&>(*this)
                ==way::Beg(*mContainer);
        }

template<dHEADER> 
    bool IteratorBaseWrapper<dSPEC>::
        End()const   
        {
            return !mContainer || 
                static_cast<const iterator&>(*this)
                ==way::End(*mContainer);
        }
template<dHEADER>
    bool IteratorBaseWrapper<dSPEC>::
        Empty()const { return End(); }

template<dHEADER>
    bool IteratorBaseWrapper<dSPEC>::
        operator!=(const IteratorBaseWrapper& rhs)const
            { return !operator==(rhs); }

template<dHEADER> 
    bool IteratorBaseWrapper<dSPEC>::
        operator==(const IteratorBaseWrapper& rhs)const
        {
            const size_t empty_this  = Empty()?     1: 0;
            const size_t empty_other = rhs.Empty()? 1: 0;
            if(empty_this + empty_other == 2)
                return true;
            if(empty_this != empty_other)
                return false;
            const iterator& _rhs = static_cast<const iterator&>(rhs);
            const iterator& me   = static_cast<const iterator&>(*this);
            return _rhs==me;
        }




}//namespace Den


#undef dHEADER
#undef dSPEC

#if defined(__GNUC__) || defined(__MINGW__) || defined(__MINGW32__)
    #pragma GCC diagnostic pop
#endif
